#include "preHeader.h"
#include "Item.h"
#include "Map/MapInstance.h"

Item::Item(Player* pOwner)
: m_pOwner(pOwner)
, m_pItemProto(NULL)
, m_itemSlotType(ItemSlotType(-1))
, m_itemSlot(ItemSlotInvalid)
{
}

Item::~Item()
{
}

WheelTimerMgr *Item::GetWheelTimerMgr()
{
	return &m_pOwner->GetMapInstance()->sWheelTimerMgr;
}

GErrorCode Item::Load(const ItemPrototype* pItemProto,
	const inst_item_prop& itemProp, uint32 itemCount, bool isNew)
{
	if (itemProp.itemTypeID == 0) {
		return CommonInternalError;
	}
	if (pItemProto == NULL) {
		pItemProto = GetDBEntry<ItemPrototype>(itemProp.itemTypeID);
		if (pItemProto == NULL) {
			return CommonInternalError;
		}
	}
	if (pItemProto->itemTypeID != itemProp.itemTypeID) {
		return CommonInternalError;
	}

	m_pEquipProto = GetDBEntry<ItemEquipPrototype>(itemProp.itemTypeID);
	m_pItemProto = pItemProto;
	m_itemProp = itemProp;

	if (isNew) {
		m_itemProp.itemGuid = m_pOwner->NewItemUniqueKey();
	}

	if (itemCount != 0) {
		m_itemProp.itemCount = itemCount;
	}
	if (m_itemProp.itemCount > pItemProto->itemStack) {
		m_itemProp.itemCount = pItemProto->itemStack;
	}

	if (m_itemProp.itemOwner >= PLAYER_UID_MIN) {
		if (m_itemProp.itemOwner == m_pOwner->GetGuidLow()) {
			m_itemProp.itemOwner = 1;
		}
	}

	return CommonSuccess;
}

void Item::SetItemSlot(ItemSlotType type, uint32 slot)
{
	m_itemSlotType = type;
	m_itemSlot = slot;
}

void Item::AddItemCount(uint32 num,
	ITEM_FLOW_TYPE flowType, params<uint32> flowParams, uint32 flags)
{
	DBGASSERT(m_pItemProto->itemStack >= m_itemProp.itemCount + num);
	m_itemProp.itemCount += num;

	if ((flags & ICF_PREVENT_SYNC_VALUE) == 0) {
		auto pQuestStorage = m_pOwner->GetQuestStorage();
		pQuestStorage->SetItemCountDirty(m_pItemProto->itemTypeID);
		pQuestStorage->OnHaveItem(
			m_pItemProto->itemTypeID, num, flowType, flowParams);
	}

	if ((flags & ICF_PREVENT_SYNC_CLIENT) == 0) {
		NetPacket pack(SMSG_ADD_ITEM_COUNT);
		pack << m_itemSlotType << m_itemSlot << m_itemProp.itemCount << num;
		m_pOwner->SendPacket(pack);
	}
}

void Item::SubItemCount(uint32 num,
	ITEM_FLOW_TYPE flowType, params<uint32> flowParams, uint32 flags)
{
	DBGASSERT(m_itemProp.itemCount > num);
	SubLeastZeroX(m_itemProp.itemCount, num);

	if ((flags & ICF_PREVENT_SYNC_VALUE) == 0) {
		auto pQuestStorage = m_pOwner->GetQuestStorage();
		pQuestStorage->SetItemCountDirty(m_pItemProto->itemTypeID);
		pQuestStorage->OnHaveItem(
			m_pItemProto->itemTypeID, 0, flowType, flowParams);
	}

	if ((flags & ICF_PREVENT_SYNC_CLIENT) == 0) {
		NetPacket pack(SMSG_SUB_ITEM_COUNT);
		pack << m_itemSlotType << m_itemSlot << m_itemProp.itemCount << num;
		m_pOwner->SendPacket(pack);
	}
}

void Item::ApplyAttributes(AttrPartProxy& proxy) const
{
	for (auto& info : m_pEquipProto->itemEquipAttrs) {
		proxy.ApplyAttribute(info.type, info.value);
	}
	for (auto& info : m_pEquipProto->itemEquipSpells) {
		proxy.ApplySpell(info.id, info.level);
	}
}
